package be.jaisy.adapter.hibernate.manager;

import java.net.URL;
import java.util.HashSet;
import java.util.Set;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.context.ThreadLocalSessionContext;


public class SessionFactoryWrapper {

	private String id;

	private URL configurationPath;

	private Set<Class<?>> dataModelClasses;

	private boolean isDirty;

	private SessionFactory sessionFactory;

	public SessionFactoryWrapper(String id) {
		super();
		this.id = id;
		this.dataModelClasses = new HashSet<Class<?>>();
		this.isDirty = true;
	}

	public String getId() {
		return id;
	}

	public Set<Class<?>> getDataModelClasses() {
		return dataModelClasses;
	}

	public void setConfigurationPath(URL configurationPath) {
		this.isDirty = true;
		this.configurationPath = configurationPath;
	}

	public boolean addDataModelClass(Class<?> dataModelClass) {
		this.isDirty = true;
		return this.dataModelClasses.add(dataModelClass);
	}

	public boolean removeDataModelClass(Class<?> dataModelClass) {
		this.isDirty = true;
		return this.dataModelClasses.remove(dataModelClass);
	}

	public SessionFactory getSessionFactory() {
		if (this.isDirty)
			return createSessionFactory();
		return this.sessionFactory;
	}

	public void close() {
		if (this.sessionFactory != null)
			this.sessionFactory.close();
	}

	private SessionFactory createSessionFactory() {
		this.close();
		if (this.configurationPath == null)
			throw new IllegalArgumentException("Cannot create SessionFactory, SessionFactory with id [" + this.id + "] not registered");
		try {
			AnnotationConfiguration config = (AnnotationConfiguration) new AnnotationConfiguration().configure(configurationPath);
			for (Class<?> dataModelClass : this.dataModelClasses) {
				config.addAnnotatedClass(dataModelClass);
			}
			config.setProperty("hibernate.current_session_context_class", ThreadLocalSessionContext.class.getName());

			this.sessionFactory = config.buildSessionFactory();
		} catch (Throwable e) {
			throw new HibernateAccessException("Cannot create SessionFactory ["+this.id+"] from configPath ["+this.configurationPath+"]", e);
		}
		this.isDirty = false;
		return this.sessionFactory;
	}
}
